home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / raid / devRaid.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  15KB  |  510 lines

  1. /* 
  2.  * devRaid.c --
  3.  *
  4.  *    This module implements the BlockDevice interface for
  5.  *    RAID level 5 disk arrays.
  6.  *    Assuming a minimum sector size of 512 bytes, RAID devices with an
  7.  *    address space of upto 2^40 bytes (~1 terra byte) are supported by
  8.  *    this driver.
  9.  *
  10.  * Copyright 1989 Regents of the University of California
  11.  * All rights reserved.
  12.  * Permission to use, copy, modify, and distribute this
  13.  * software and its documentation for any purpose and without
  14.  * fee is hereby granted, provided that the above copyright
  15.  * notice appear in all copies.  The University of California
  16.  * makes no representations about the suitability of this
  17.  * software for any purpose.  It is provided "as is" without
  18.  * express or implied warranty.
  19.  */
  20.  
  21. #ifndef lint
  22. static char rcsid[] = "$Header: /sprite/src/kernel/raid/RCS/devRaid.c,v 1.16 91/06/27 12:07:14 eklee Exp $ SPRITE (Berkeley)";
  23. #endif /* not lint */
  24.  
  25. #include "sync.h"
  26. #include <sprite.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include "fs.h"
  30. #include "dev.h"
  31. /*
  32. #include "devDiskLabel.h"
  33. #include "devDiskStats.h"
  34. */
  35. #include "devBlockDevice.h"
  36. #include "devRaid.h"
  37. #include "devRaidUtil.h"
  38. #include "dev/raid.h"
  39. #include "semaphore.h"
  40. #include "devRaidLog.h"
  41. #include "stdlib.h"
  42. #include "dbg.h"
  43. #include "devRaidProto.h"
  44.  
  45. static ReturnStatus StripeBlockIOProc();
  46. static ReturnStatus RaidBlockIOProc();
  47. static ReturnStatus ReleaseProc();
  48. static ReturnStatus IOControlProc();
  49.  
  50. /*
  51.  * A RAID device must have a minor number between 0 and 31 inclusive.
  52.  */
  53. Raid raidArray[] = {
  54.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 0")},
  55.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 1")},
  56.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 2")},
  57.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 3")},
  58.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 4")},
  59.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 5")},
  60.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 6")},
  61.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 7")},
  62.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 8")},
  63.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 9")},
  64.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 10")},
  65.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 11")},
  66.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 12")},
  67.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 13")},
  68.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 14")},
  69.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 15")},
  70.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 16")},
  71.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 17")},
  72.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 18")},
  73.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 19")},
  74.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 20")},
  75.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 21")},
  76.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 22")},
  77.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 23")},
  78.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 24")},
  79.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 25")},
  80.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 26")},
  81.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 27")},
  82.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 28")},
  83.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 29")},
  84.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 30")},
  85.     {RAID_INVALID, Sync_SemInitStatic("devRaid.c: RAID unit 31")},
  86. };
  87. int numRaid = sizeof(raidArray)/sizeof(Raid);
  88.  
  89.  
  90. /*
  91.  *----------------------------------------------------------------------
  92.  *
  93.  * DevRaidAttach --
  94.  *
  95.  *    Attach a RAID logical device.
  96.  *
  97.  * Results:
  98.  *    The DevBlockDeviceHandle of the device.
  99.  *
  100.  * Side effects:
  101.  *    Modifies raidArray data structure.
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105.  
  106. DevBlockDeviceHandle *
  107. DevRaidAttach(devicePtr)
  108.     Fs_Device    *devicePtr;    /* The device to attach. */
  109. {
  110.     RaidHandle    *handlePtr;
  111.     Raid    *raidPtr;
  112.  
  113.     if ( devicePtr->unit >= numRaid ) {
  114.         return (DevBlockDeviceHandle *) NIL;
  115.     }
  116.     raidPtr = &raidArray[devicePtr->unit];
  117.     MASTER_LOCK(&raidPtr->mutex);
  118.     if ( raidPtr->state == RAID_INVALID ) {
  119.     raidPtr->state = RAID_ATTACHED;
  120.     MASTER_UNLOCK(&raidPtr->mutex);
  121. #ifdef TESTING
  122.     Sync_CondInit(&raidPtr->waitExclusive);
  123.     Sync_CondInit(&raidPtr->waitNonExclusive);
  124. #endif TESTING
  125.     Raid_InitStripeLocks();
  126.     InitDebugMem();
  127.     raidPtr->devicePtr = devicePtr;
  128.     Raid_Lock(raidPtr);
  129.     } else {
  130.     MASTER_UNLOCK(&raidPtr->mutex);
  131.     }
  132.  
  133.     handlePtr = (RaidHandle *) malloc(sizeof(RaidHandle));
  134.     /*
  135.      * 'S' means data striping only, no parity.
  136.      * We use a different blockIOproc to support this function.
  137.      */
  138.     if (raidPtr->parityConfig == 'S') {
  139.     handlePtr->blockHandle.blockIOProc = StripeBlockIOProc;
  140.     } else {
  141.     handlePtr->blockHandle.blockIOProc = RaidBlockIOProc;
  142.     }
  143.     handlePtr->blockHandle.releaseProc = ReleaseProc;
  144.     handlePtr->blockHandle.IOControlProc = IOControlProc;
  145.     handlePtr->blockHandle.minTransferUnit = 1 << raidPtr->logBytesPerSector;
  146.     handlePtr->blockHandle.maxTransferSize = RAID_MAX_XFER_SIZE;
  147.     handlePtr->devPtr = devicePtr;
  148.     handlePtr->raidPtr = &raidArray[devicePtr->unit];
  149.  
  150.     return (DevBlockDeviceHandle *) handlePtr;
  151. }
  152.  
  153.  
  154. /*
  155.  *----------------------------------------------------------------------
  156.  *
  157.  * ReleaseProc --
  158.  *
  159.  *    Block device release proc.
  160.  *
  161.  * Results:
  162.  *    Return status.
  163.  *
  164.  * Side effects:
  165.  *    Frees device handle.
  166.  *
  167.  *----------------------------------------------------------------------
  168.  */
  169.  
  170. static ReturnStatus
  171. ReleaseProc(handlePtr)
  172.     RaidHandle    *handlePtr; /* Handle pointer of device. */
  173. {
  174.     /*
  175.      * Note:  Only the handle is deallocated.
  176.      * The Raid data structures are never deallocated and stay around forever.
  177.      */
  178.     free((char *) handlePtr);
  179.     return SUCCESS;
  180. }
  181.  
  182.  
  183. /*
  184.  *----------------------------------------------------------------------
  185.  *
  186.  * IOControlProc --
  187.  *
  188.  *      Do a special operation on a RAID device.
  189.  *
  190.  * Results:
  191.  *      None.
  192.  *
  193.  * Side effects:
  194.  *      Depends on operation.
  195.  *
  196.  *----------------------------------------------------------------------
  197.  */
  198.  
  199. typedef struct {
  200.     Sema     sema;
  201.     ReturnStatus status;
  202. } IOCControl;
  203.  
  204. static void
  205. iocDoneProc(iocCtrlPtr, status)
  206.     IOCControl    *iocCtrlPtr;
  207.     ReturnStatus status;
  208. {
  209.     printf("RAID:MSG:IOC completed.\n");
  210.     if (status != SUCCESS) {
  211.     printf("RAID:ERR:IOC failed.\n");
  212.     }
  213.     iocCtrlPtr->status = status;
  214.     UpSema(&iocCtrlPtr->sema);
  215. }
  216.  
  217. static ReturnStatus
  218. IOControlProc(handlePtr, ioctlPtr, replyPtr) 
  219.     DevBlockDeviceHandle    *handlePtr;
  220.     Fs_IOCParam            *ioctlPtr;
  221.     Fs_IOReply            *replyPtr;
  222. {
  223.     static char  *IObuf;
  224.     RaidHandle     *raidHandlePtr   = (RaidHandle *) handlePtr;
  225.     Raid         *raidPtr         = raidHandlePtr->raidPtr;
  226.     RaidIOCParam *raidIOCParamPtr = (RaidIOCParam *) ioctlPtr->inBuffer;
  227.     DevBlockDeviceRequest *requestPtr =
  228.         (DevBlockDeviceRequest *) ioctlPtr->inBuffer;
  229.     int          col;
  230.     int          row;
  231.     ReturnStatus  status;
  232.     IOCControl      iocCtrl;
  233.  
  234.     if (raidIOCParamPtr == (RaidIOCParam *) NIL) {
  235.     printf("RAID:MSG:IOControlProc IOC == NIL\n");
  236.     return FAILURE;
  237.     }
  238.     col = raidIOCParamPtr->col;
  239.     row = raidIOCParamPtr->row;
  240.  
  241.     bzero((char *) replyPtr, sizeof(Fs_IOReply));
  242.  
  243.     switch(ioctlPtr->command) {
  244.     case IOC_DEV_RAID_PRINT:
  245.     if (raidPtr->state != RAID_VALID) {
  246.         return SUCCESS;
  247.     }
  248.     PrintRaid(raidPtr);
  249.     return SUCCESS;
  250.     case IOC_DEV_RAID_RECONFIG:
  251.     status = Raid_Configure(raidPtr, raidIOCParamPtr->buf);
  252.     return status;
  253.     case IOC_DEV_RAID_FAIL:
  254.     if (raidPtr->state != RAID_VALID) {
  255.         return FAILURE;
  256.     }
  257.     if (row < 0 || row >= raidPtr->numRow) {
  258.         printf("RAID:MSG:row=%d out of range on ioctl call", row);
  259.         return FAILURE;
  260.     }
  261.     if (col < 0 || col >= raidPtr->numCol) {
  262.         printf("RAID:MSG:col=%d out of range on ioctl call", col);
  263.         return FAILURE;
  264.     }
  265.     Raid_FailDisk(raidPtr, col, row, raidPtr->disk[col][row]->version);
  266.     return SUCCESS;
  267.     case IOC_DEV_RAID_REPLACE:
  268.     if (raidPtr->state != RAID_VALID) {
  269.         return FAILURE;
  270.     }
  271.     if (row < 0 || row >= raidPtr->numRow) {
  272.         printf("RAID:MSG:row=%d out of range on ioctl call", row);
  273.         return FAILURE;
  274.     }
  275.     if (col < 0 || col >= raidPtr->numCol) {
  276.         printf("RAID:MSG:col=%d out of range on ioctl call", col);
  277.         return FAILURE;
  278.     }
  279.     Raid_ReplaceDisk(raidPtr, col, row, raidPtr->disk[col][row]->version,
  280.         raidIOCParamPtr->type, raidIOCParamPtr->unit, 0);
  281.     return SUCCESS;
  282.     case IOC_DEV_RAID_HARDINIT:
  283.     if (raidPtr->state != RAID_VALID) {
  284.         return FAILURE;
  285.     }
  286.     InitSema(&iocCtrl.sema, "Raid HardInit", 0);
  287.     Raid_InitiateHardInit(raidPtr,
  288.         raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
  289.         iocDoneProc, (ClientData) &iocCtrl,
  290.         raidIOCParamPtr->ctrlData);
  291.     DownSema(&iocCtrl.sema);
  292.     return iocCtrl.status;
  293.     case IOC_DEV_RAID_PARITYCHECK:
  294.     if (raidPtr->state != RAID_VALID) {
  295.         return FAILURE;
  296.     }
  297.     InitSema(&iocCtrl.sema, "Raid ParityCheck", 0);
  298.     Raid_InitiateParityCheck(raidPtr,
  299.         raidIOCParamPtr->startStripe, raidIOCParamPtr->numStripe,
  300.         iocDoneProc, (ClientData) &iocCtrl,
  301.         raidIOCParamPtr->ctrlData);
  302.     DownSema(&iocCtrl.sema);
  303.     return iocCtrl.status;
  304.     case IOC_DEV_RAID_RECONSTRUCT:
  305.     if (raidPtr->state != RAID_VALID) {
  306.         return FAILURE;
  307.     }
  308.     InitSema(&iocCtrl.sema, "Raid Reconstruct", 0);
  309.     Raid_InitiateReconstruction(raidPtr, col, row,
  310.         raidPtr->disk[col][row]->version,
  311.         raidIOCParamPtr->numStripe, raidIOCParamPtr->uSec,
  312.         iocDoneProc, (ClientData) &iocCtrl,
  313.         raidIOCParamPtr->ctrlData);
  314.     DownSema(&iocCtrl.sema);
  315.     return iocCtrl.status;
  316.     case IOC_DEV_RAID_IO:
  317.     if (raidPtr->state != RAID_VALID) {
  318.         return FAILURE;
  319.     }
  320.     if (!IObuf) {
  321.         IObuf = (char *) malloc(1024*1024);
  322.     }
  323.     requestPtr->buffer = IObuf;
  324.     return Dev_BlockDeviceIOSync(handlePtr, requestPtr,
  325.         (int *)ioctlPtr->outBuffer);
  326.     case IOC_DEV_RAID_LOCK:
  327.     Raid_Lock(raidPtr);
  328.     return SUCCESS;
  329.     case IOC_DEV_RAID_UNLOCK:
  330.     Raid_Unlock(raidPtr);
  331.     return SUCCESS;
  332.     case IOC_DEV_RAID_SAVE_STATE:
  333.     if (raidPtr->state != RAID_VALID) {
  334.         return FAILURE;
  335.     }
  336.     status = Raid_SaveState(raidPtr);
  337.     if (status != SUCCESS) {
  338.         printf("RAID:MSG:Could not checkpoint state.\n");
  339.     }
  340.     return status;
  341.     case IOC_DEV_RAID_ENABLE_LOG:
  342.     Raid_EnableLog(raidPtr);
  343.     return SUCCESS;
  344.     case IOC_DEV_RAID_DISABLE_LOG:
  345.     Raid_DisableLog(raidPtr);
  346.     return SUCCESS;
  347.     case IOC_DEV_RAID_RESTORE_STATE:
  348.     raidPtr->logDev.type = raidIOCParamPtr->type;
  349.     raidPtr->logDev.unit = raidIOCParamPtr->unit;
  350.     raidPtr->logDevOffset = raidIOCParamPtr->startStripe;
  351.     /*
  352.      * Attach log device.
  353.      */
  354.     raidPtr->logHandlePtr = Dev_BlockDeviceAttach(&raidPtr->logDev);
  355.     if (raidPtr->logHandlePtr == (DevBlockDeviceHandle *) NIL) {
  356.         printf("RAID:ERR:Could not attach log device %d %d\n",
  357.             raidPtr->logDev.type, raidPtr->logDev.unit);
  358.         return FAILURE;
  359.     }
  360.     status = Raid_RestoreState(raidPtr);
  361.     if (status != SUCCESS) {
  362.         printf("RAID:MSG:Could not restore state.\n");
  363.     }
  364.     return status;
  365.     default:
  366.     return SUCCESS;
  367.     }
  368. }
  369.  
  370.  
  371. /*
  372.  *----------------------------------------------------------------------
  373.  *
  374.  * StripeBlockIOProc --
  375.  *    Perform block IO w/o parity, i.e. data striping only,
  376.  *    on specified RAID device.
  377.  *
  378.  * Results:
  379.  *    None.
  380.  *
  381.  * Side effects:
  382.  *    The disk write, if operation == FS_WRITE.
  383.  *
  384.  *----------------------------------------------------------------------
  385.  */
  386. static ReturnStatus
  387. StripeBlockIOProc(handlePtr, requestPtr) 
  388.     DevBlockDeviceHandle  *handlePtr;
  389.     DevBlockDeviceRequest *requestPtr;
  390. {
  391.     RaidHandle       *raidHandlePtr;
  392.     Raid        *raidPtr;
  393.     unsigned         firstSector;
  394.     unsigned        nthSector;
  395.     unsigned        numSector;
  396.  
  397.     raidHandlePtr = (RaidHandle *) handlePtr;
  398.     raidPtr      = raidHandlePtr->raidPtr;
  399.  
  400.     /*
  401.      * Check if operation valid.
  402.      */
  403.     if (!((requestPtr->operation == FS_READ) ||
  404.           (requestPtr->operation == FS_WRITE))) {
  405.     panic("Unknown operation %d in RAID blockIOProc.\n", 
  406.         requestPtr->operation);
  407.     return DEV_INVALID_ARG;
  408.     }
  409.  
  410.     /*
  411.      * Convert byte addresses to sector addresses.
  412.      */
  413.     firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
  414.         (requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
  415.     numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
  416.     nthSector = firstSector + numSector;
  417.  
  418.     /*
  419.      * Check that addresses are within the range supported by the device.
  420.      */
  421.     if ( firstSector >= raidPtr->numSector ) {
  422.     requestPtr->doneProc(requestPtr, FAILURE, 0);
  423.     return SUCCESS;
  424.     } 
  425.  
  426.     /*
  427.      * Prevent overruns.
  428.      */
  429.     if ( nthSector > raidPtr->numSector ) {
  430.         nthSector = raidPtr->numSector;
  431.     } 
  432.  
  433.     Raid_InitiateSimpleStripeIOs(raidPtr, requestPtr->operation,
  434.             firstSector, nthSector, requestPtr->buffer,
  435.             requestPtr->doneProc, (ClientData) requestPtr,
  436.             requestPtr->ctrlData[0]);
  437.     return SUCCESS;
  438. }
  439.  
  440.  
  441. /*
  442.  *----------------------------------------------------------------------
  443.  *
  444.  * RaidBlockIOProc --
  445.  *
  446.  *    Perform block IO (w/ parity) on specified RAID device.
  447.  *
  448.  * Results:
  449.  *    None.
  450.  *
  451.  * Side effects:
  452.  *    The disk write, if operation == FS_WRITE.
  453.  *
  454.  *----------------------------------------------------------------------
  455.  */
  456.  
  457. static ReturnStatus
  458. RaidBlockIOProc(handlePtr, requestPtr) 
  459.     DevBlockDeviceHandle  *handlePtr;
  460.     DevBlockDeviceRequest *requestPtr;
  461. {
  462.     RaidHandle       *raidHandlePtr;
  463.     Raid        *raidPtr;
  464.     unsigned         firstSector;
  465.     unsigned        nthSector;
  466.     unsigned        numSector;
  467.  
  468.     raidHandlePtr = (RaidHandle *) handlePtr;
  469.     raidPtr      = raidHandlePtr->raidPtr;
  470.  
  471.     /*
  472.      * Check if operation valid.
  473.      */
  474.     if (!((requestPtr->operation == FS_READ) ||
  475.           (requestPtr->operation == FS_WRITE))) {
  476.     panic("Unknown operation %d in RAID blockIOProc.\n", 
  477.         requestPtr->operation);
  478.     return DEV_INVALID_ARG;
  479.     }
  480.  
  481.     /*
  482.      * Convert byte addresses to sector addresses.
  483.      */
  484.     firstSector = (requestPtr->startAddress >> raidPtr->logBytesPerSector) |
  485.         (requestPtr->startAddrHigh<<(BITS_PER_ADDR-raidPtr->logBytesPerSector));
  486.     numSector = requestPtr->bufferLen >> raidPtr->logBytesPerSector;
  487.     nthSector = firstSector + numSector;
  488.  
  489.     /*
  490.      * Check that addresses are within the range supported by the device.
  491.      */
  492.     if ( firstSector >= raidPtr->numSector ) {
  493.     requestPtr->doneProc(requestPtr, FAILURE, 0);
  494.     return SUCCESS;
  495.     } 
  496.  
  497.     /*
  498.      * Prevent overruns.
  499.      */
  500.     if ( nthSector > raidPtr->numSector ) {
  501.         nthSector = raidPtr->numSector;
  502.     } 
  503.  
  504.     Raid_InitiateStripeIOs(raidPtr, requestPtr->operation,
  505.             firstSector, nthSector, requestPtr->buffer,
  506.             requestPtr->doneProc, (ClientData) requestPtr,
  507.             requestPtr->ctrlData[0]);
  508.     return SUCCESS;
  509. }
  510.